package com.zzjson.datasource.service.impl;

import com.zzjson.datasource.entity.User;
import com.zzjson.datasource.entity.UserPay;
import com.zzjson.datasource.mapper.UserPayMapper;
import com.zzjson.datasource.service.OrderService;
import com.zzjson.datasource.service.PayService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

@Service
public class OrderServiceImpl implements OrderService {

	private static final Logger logger = LoggerFactory.getLogger(OrderServiceImpl.class);

	@Autowired
	PayService payService;

	@Autowired
	UserPayMapper userPayMapper;

	//    @Transactional
	@Override
	public void placeOrderAndFindWithRequireNew(String userId) {
		logger.info("准备执行 payAndFindWithRequireNew.pay()方法");
		payService.payAndFindWithRequireNew(userId);
	}

	@Override
	public void placeOrderAndFindWithRequireNewInnerCall(String userId) {
		logger.info("准备执行 payAndFindWithRequireNewInnerCall.pay()方法");
		payService.payAndFindWithRequireNewInnerCall(userId);
	}

	@Override
	public void placeOrderAndFindWithRequire(String userId) {
		payService.payAndFindWithRequire(userId);
	}

	@Override
	public void placeOrderAndFindNested(String userId) {
		payService.payAndFindWithNested(userId);
	}

	@Override
	public void placeOrder2(String userId) {
		payService.pay2(userId);
	}

	@Override
	public void debugDatasourceTransByThreadLocal() {
		payService.pay3();
	}

	/**
	 * 内层抛异常
	 */
	@Transactional
	@Override
	public void testPropogationNested() {
		User user1 = new User();
		user1.setId("283" + (System.currentTimeMillis() % 100));
		UserPay userPay1 = new UserPay();
		userPay1.setId(user1.getId());
		userPay1.setName(user1.getName());
		userPay1.setAmount(10);

		try {
			payService.payWithPropagationNested(user1); //因为是Nested会产生SavePoint，这个方法出现异常还会回滚到这里但是事务并未提交
		} catch (RuntimeException e) //这里外部事务根据自己的配置决定是rollback还是commit
		{
			//业务C
			System.out.println("orderServiceImpl.testPropogationNested" + e.getMessage());
			userPay1.setName(user1.getName() + "insert Error");
			userPayMapper.addUserPay(userPay1);
		}
	}

	/**
	 * 外层抛异常
	 */
	@Transactional
	@Override
	public void testPropogationNestedExceptionOuter() {
		User user1 = new User();
		user1.setId("155" + (System.currentTimeMillis() % 100));
		UserPay userPay1 = new UserPay();
		userPay1.setId(user1.getId());
		userPay1.setName(user1.getName());
		userPay1.setAmount(10);
		payService.payWithPropagationNestedOuter(user1); //因为是Nested会产生SavePoint，这个方法出现异常还会回滚到这里但是事务并未提交
		throw new RuntimeException("exception outer");
//        System.out.println("抛异常拉");
	}

	/**
	 * 外层抛异常
	 */
	@Transactional
	@Override
	public void testPropogationNestedExceptionOuterNotRuntimeException() throws Exception {
		User user1 = new User();
		user1.setId("157" + (System.currentTimeMillis() % 100));
		UserPay userPay1 = new UserPay();
		userPay1.setId(user1.getId());
		userPay1.setName(user1.getName());
		userPay1.setAmount(10);
		payService.payWithPropagationNestedOuter(user1); //因为是Nested会产生SavePoint，这个方法出现异常还会回滚到这里但是事务并未提交
		throw new Exception("抛异常了");
//        System.out.println("抛异常拉");
	}

	/**
	 * 内存抛异常
	 */
	@Transactional
	@Override
	public void testPropogationRequireNew() {
		User user1 = new User();
		user1.setId("390" + (System.currentTimeMillis() % 100));
		user1.setName(user1.getId() + "name");
		UserPay userPay1 = new UserPay();
		userPay1.setId(user1.getId());
		userPay1.setName(user1.getName());
		userPay1.setAmount(10);
		try {
			payService.payWithPropagationNew(user1);
			System.out.println("抛异常啦");
		} catch (RuntimeException e) {
			//业务C
			System.out.println("orderServiceImpl.testPropogationRequireNew" + e.getMessage());
			userPay1.setName(user1.getName() + "insert Error");
			userPayMapper.addUserPay(userPay1);
		}
	}

	/**
	 * requireNew里面的事务提交了<br>
	 */
	@Transactional
	@Override
	public void testPropogationRequireNewOuter() {
		User user1 = new User();
		user1.setId("793" + (System.currentTimeMillis() % 100));
		user1.setName(user1.getId() + "name");
		UserPay userPay1 = new UserPay();
		userPay1.setId(user1.getId());
		userPay1.setName(user1.getName());
		userPay1.setAmount(10);

		payService.payWithPropagationNewOuter(user1);
		throw new RuntimeException("testPropogationRequireNewOuter exception error");
	}
}